var Passport = require('passport'),
    LocalStrategy = require('passport-local').Strategy,
    ideas = require('../models/idea'),
    comments = require('../models/comment'),
    votes = require('../models/vote'),
    users = require('../models/user'),
    logger = require('../models/logger'),
    apiHandler = require('../services/api-handler'),
    stringConstant = require('../helpers/string-constants'),
    countryHelper = require('../helpers/country'),
    jWT = require('../helpers/jwt'),
    authToken = require('../models/auth-token'),
    mailer = require('../mailer/mailer'),
    activity = require('../models/activity'),
    versionModel = require('../models/version'),
    JWT = require('jsonwebtoken'),
    jwtSecret = require('../config/secrets').jwtSecret,
    timeAgo = require('node-time-ago');

exports.register = function (req, res) {
    var bodyParams = req.body,
        name = bodyParams.name,
        email = bodyParams.email,
        password = bodyParams.password,
        passwordConfirm = bodyParams.passwordConfirm,
        emailRegex = new RegExp(stringConstant.VALID_EMAIL_REGEX),
        firstName = '', lastName = '', fullName = '', newUser, confirmationToken, confirmationUrl;
    if (!name || !email || !password) {
        apiHandler.setErrorResponse('REQUIRED_FIELDS_MISSING', res);
    } else if (!emailRegex.test(email)) {
        apiHandler.setErrorResponse('INVALID_EMAIL_ADDRESS', res);
    } else if (password && password !== passwordConfirm) {
        apiHandler.setErrorResponse('CONFIRM_PASSWORD_NOT_SAME', res);
    } else {
        fullName = name.split(' ');
        if (fullName.length > 1) {
            lastName = fullName[fullName.length - 1];
            for (var i = 0; i < fullName.length - 1; i++) {
                firstName = firstName + ' ' + fullName[i];
            }
        } else {
            firstName = fullName[0];
            lastName = '';
        }
        bodyParams.firstName = firstName;
        bodyParams.lastName = lastName;
        versionModel.assignRandomVersion(function (err, versions) {
            if (err) {
                apiHandler.setErrorResponse('NO_VERSIONS', res);
            } else {

                 bodyParams.version = versions[0].name || "Version_7";

                 versionModel.updateVersionCount(versions[0].name || "Version_7", bodyParams.gender, '', '');

                newUser = new users(bodyParams);
                users.createUser(newUser, function (err, user) {
                    if (err) {
                        if (err.code === 11000) {
                            apiHandler.setErrorResponse('EMAIL_ALREADY_EXIST', res);
                            apiHandler.setErrorResponse('EMAIL_ALREADY_EXIST', res);
                        } else {
                            apiHandler.setErrorResponse('UNKNOWN_ERROR', res);
                        }
                    } else {
                        confirmationToken = jWT.getConfirmationToken(newUser);
                        users.updateConfirmationToken(confirmationToken, function (err, userDetails) {
                            if (err) {
                                apiHandler.setErrorResponse('UNKNOWN_ERROR', res);
                            } else {
                                confirmationUrl = ':3001/v1/users/confirm?token=' + confirmationToken;
                                mailer.sendConfirmationMail(firstName, email, confirmationUrl)
                                    .then(function (success) {
                                        var token = jWT.getLoginToken(user);
                                        var newToken = new authToken({
                                            user: user,
                                            token: token
                                        });
                                        authToken.createToken(newToken, function (err, authUser) {
                                            if (err) {
                                                req.user = null;
                                                apiHandler.setErrorResponse('LOGIN_FAILED', res);
                                            } else {
                                                var data = {
                                                    token: token,
                                                    user: user
                                                };
                                                apiHandler.setSuccessResponse(data, res);
                                            }
                                        });
                                    })
                                    .catch(function (err) {
                                        user.remove();
                                        apiHandler.setErrorResponse('ERROR_IN_USER_ADDITION', res);
                                    });
                            }
                        });
                    }
                });
            }
        });
    }
};

Passport.use(new LocalStrategy(
    function (email, password, done) {
        users.getUserByEmail(email, function (err, user) {
            if (err) {
                return done(null, false, {message: 'INVALID_USER'});
            }
            if (!user) {
                return done(null, false, {message: 'INVALID_USER'});
            }
            users.comparePassword(password, user.password, function (err, isMatch) {
                if (err) {
                    return done(null, false, {message: 'UNKNOWN_ERROR'});
                } else {
                    if (isMatch) {
                        return done(null, user);
                    } else {
                        return done(null, false, {message: 'PASSWORD_DOES_NOT_MATCH'});
                    }
                }
            });
        });
    }
));

exports.login = function (req, res, next) {
    console.log("login")
    Passport.authenticate('local', function (err, user, info) {
        var token, newToken;
        if (!err && !user && info) {
            apiHandler.setErrorResponse(info.message, res);
        } else if (user) {

            // To allow all locked and unlocked version

            token = jWT.getLoginToken(user);
            newToken = new authToken({
                user: user,
                token: token
            });
            authToken.createToken(newToken, function (err, authUser) {
                if (err) {
                    req.user = null;
                    apiHandler.setErrorResponse('LOGIN_FAILED', res);
                } else {
                    var data = {token: token, user: user};
                    apiHandler.setSuccessResponse(data, res);
                }
            });


            // To allow only unlocked versions
            // versionModel.getLockedVersion(function (err, versions) {
            //     var versionsArray = [];
            //     versions.forEach(function (u) {
            //         versionsArray.push(u.name)
            //     });
            //     if (versionsArray.indexOf(user.version) >= 0) {
            //         apiHandler.setErrorResponse('LOGIN_FAILED_DUE_TO_VERSION', res);
            //     } else {
            //         token = jWT.getLoginToken(user);
            //         newToken = new authToken({
            //             user: user,
            //             token: token
            //         });
            //         authToken.createToken(newToken, function (err, authUser) {
            //             if (err) {
            //                 req.user = null;
            //                 apiHandler.setErrorResponse('LOGIN_FAILED', res);
            //             } else {
            //                 var data = {token: token, user: user};
            //                 apiHandler.setSuccessResponse(data, res);
            //             }
            //         });
            //     }
            // });

        } else {
            apiHandler.setErrorResponse('LOGIN_FAILED', res);
        }
    })(req, res, next);
};

Passport.serializeUser(function (user, done) {
    done(null, user.id);
});

Passport.deserializeUser(function (id, done) {
    users.getUserById(id, function (err, user) {
        done(err, user);
    });
});

exports.me = function (req, res) {
    var user = req.user;
    apiHandler.setSuccessResponse(user, res);
};

exports.getAllUsers = function (req, res) {
    users.getAllUsers(apiHandler.handler.check(res, 'NO_USERS', function (users) {
        apiHandler.setSuccessResponse(users, res);
    }));
};

exports.activateID = function (req, res) {
    users.getUserById(req.params.id, apiHandler.handler.check(res, 'INVALID_USER', function (user) {
        user.isActive = true;
        user.save(function (err) {
            if (err) {
                var errorLog = new logger({
                    details: err,
                    activity: stringConstant.ACTIVATION_ACTIVITY
                });
                errorLog.save();
            }
        });
        apiHandler.setSuccessResponse('', res);
    }));
};

exports.deactivateID = function (req, res) {
    users.getUserById(req.params.id, apiHandler.handler.check(res, 'INVALID_USER', function (user) {
        user.isActive = false;
        user.save(function (err) {
            if (err) {
                var errorLog = new logger({
                    details: err,
                    activity: stringConstant.DEACTIVATION_ACTIVITY
                });
                errorLog.save();
            }
        });
        apiHandler.setSuccessResponse('', res);
    }));
};

exports.changepassword = function (req, res) {
    var reqBody = req.body,
        email = req.user.email,
        oldPassword = reqBody.old_password,
        newPassword = reqBody.new_password,
        newPasswordConfirm = reqBody.new_password_confirm;

    if (newPassword === newPasswordConfirm) {
        users.getUserByEmail(email, function (err, user) {
            users.comparePassword(oldPassword, user.password, apiHandler.handler.check(res, 'ERROR_IN_UPDATE_PASSWORD', function (isMatch) {
                if (isMatch) {
                    user.password = newPassword;
                    user.save(function (err) {
                        if (err) {
                            var errorLog = new logger({
                                details: err,
                                activity: stringConstant.PASSWORD_CHANGE_ACTIVITY
                            });
                            errorLog.save();
                        }
                    });
                    apiHandler.setSuccessResponse('', res);
                } else {
                    apiHandler.setErrorResponse('PASSWORD_DOES_NOT_MATCH', res);
                }
            }));
        });
    } else {
        apiHandler.setErrorResponse('CONFIRM_PASSWORD_NOT_SAME', res);
    }
};

exports.confirm = function (req, res) {
    var token = req.query.token || req.headers['x-access-token'];
    jWT.isValidToken(token, apiHandler.handler.check(res, 'INVALID_TOKEN', function (decoded) {
        users.getUserByConfirmationToken(token, apiHandler.handler.check(res, 'INVALID_USER', function (user) {
            if (user) {
                user.isVerified = true;
                user.confirmationToken = '';
                user.save(function (err) {
                    if (err) {
                        var errorLog = new logger({
                            details: err,
                            activity: stringConstant.ACCOUNT_CONFIRMATION_ACTIVITY
                        });
                        errorLog.save();
                    }
                });
                apiHandler.setSuccessResponse('', res);
            } else {
                apiHandler.setSuccessResponse('', res);
            }
        }));
    }));
};

exports.forgotpassword = function (req, res) {
    var reqBody = req.body,
        email = reqBody.email,
        passwordResetUrl,
        passwordResetToken;

    users.getUserByEmail(email, apiHandler.handler.check(res, 'INVALID_USER', function (user) {
        if (!user) {
            apiHandler.setErrorResponse('INVALID_USER', res);
        } else {
            if (user.passwordResetToken) {
                passwordResetToken = user.passwordResetToken;
            } else {
                passwordResetToken = jWT.getResetPasswordToken(email);
                user.passwordResetToken = passwordResetToken;
                user.save(function (err) {
                    if (err) {
                        var errorLog = new logger({
                            details: err,
                            activity: stringConstant.FORGOT_PASSWORD_ACTIVITY
                        });
                        errorLog.save();
                    }
                });
            }
            passwordResetUrl = '/#/passwordreset?token=' + passwordResetToken + '&user_id=' + user._id;
            mailer.sendPasswordResetMail(email, passwordResetUrl, user.firstName)
                .then(function (success) {
                    apiHandler.setSuccessResponse('', res);
                })
                .catch(function (err) {
                    user.remove();
                    apiHandler.setErrorResponse('ERROR_WHILE_MAIL_SENDING', res);
                });
        }
    }));
};

exports.tokenCheck = function (req, res) {
    var token = req.headers.token || req.headers['x-access-token']
    JWT.verify(token, jwtSecret, function (err) {
        if (!err) {
            apiHandler.setSuccessResponse('', res);
        }
        else {
            apiHandler.setErrorResponse('INVALID_TOKEN', res);
        }
    });
};

exports.passwordreset = function (req, res) {
    var reqBody = req.body,
        newPassword = reqBody.new_password,
        newPasswordConfirm = reqBody.new_password_confirm,
        token = req.headers.token || req.headers['x-access-token'];
    jWT.isValidToken(token, apiHandler.handler.check(res, 'INVALID_TOKEN', function (decoded) {
        if (newPassword === newPasswordConfirm) {
            users.getUserById(req.query.user_id, apiHandler.handler.check(res, 'UNKNOWN_ERROR', function (user) {
                if (user && user.passwordResetToken !== token) {
                    apiHandler.setErrorResponse('TOKEN_EXPIRED', res);
                } else {
                    user.password = newPassword;
                    user.passwordResetToken = '';
                    user.save(function (err) {
                        if (err) {
                            var errorLog = new logger({
                                details: err,
                                activity: stringConstant.PASSWORD_RESET_ACTIVITY
                            });
                            errorLog.save();
                        }
                    });
                    apiHandler.setSuccessResponse('', res);
                }
            }));
        } else {
            apiHandler.setErrorResponse('CONFIRM_PASSWORD_NOT_SAME', res);
        }
    }));
};

exports.logout = function (req, res) {
    var token = req.headers.token || req.headers['x-access-token'];
    authToken.deleteUserToken(token, apiHandler.handler.check(res, 'PLEASE_TRY_AGAIN', function (users) {
        req.logout();
        apiHandler.setSuccessResponse('', res);
    }));
};

exports.getAuthor = function (req, res) {
    users.getAuthor(req.body.author, apiHandler.handler.check(res, 'NO_USERS', function (author) {
        apiHandler.setSuccessResponse(author, res);
    }));
};

exports.viewProfile = function (req, res) {
    var ID;
    if (req.body._id) {
        ID = req.body._id;
    } else {
        ID = req.user._id;
    }
    users.viewProfile(ID, apiHandler.handler.check(res, 'NO_USERS', function (profile) {
        if (!profile) {
            apiHandler.setErrorResponse('NO_USERS', res);
        } else {
            ideas.getIdeasByUserId(ID, apiHandler.handler.check(res, 'NO_IDEA_FOUND', function (idea) {
                var likesCount = 0,
                    commentsOnUsersIdea = 0,
                    points = 0,
                    ideaCount = idea.length;
                for (var i = 0; i < ideaCount; i++) {
                    likesCount += idea[i].likes;
                    commentsOnUsersIdea += idea[i].commentCount;
                    points += idea[i].points;
                }
                comments.getCommentsByUserId(ID, apiHandler.handler.check(res, 'NO_COMMENT_FOUND', function (comment) {
                    var commentCount = comment.length;
                    votes.getVoteCountByUserId(ID, apiHandler.handler.check(res, 'NO_VOTE_ON_IDEA_FOUND', function (voteCount) {
                        activity.getAllActivities(ID, req.body, apiHandler.handler.check(res, 'NO_ACTIVITY', function (activity) {
                            activity.forEach(function (activityData) {
                                activityData.timeAgo = timeAgo(activityData.createdAt);
                            });
                            var data = {
                                "profile": profile,
                                "ideaCount": ideaCount,
                                "likesCount": likesCount,
                                "commentsOnUsersIdea": commentsOnUsersIdea,
                                "commentCount": commentCount,
                                "voteCount": voteCount,
                                "points": points,
                                "activity": activity
                            };
                            apiHandler.setSuccessResponse(data, res);
                        }));
                    }));
                }));
            }));
        }
    }));
};

exports.updateProfile = function (req, res) {
    users.viewProfile(req.body._id, apiHandler.handler.check(res, 'NO_USERS', function (profile) {
        if (!profile) {
            apiHandler.setErrorResponse('NO_USERS', res);
        } else {
            profile.address = "";
            profile.city = "";
            profile.state = "";
            profile.country = "";
            profile.aboutMe = "";
            var bodyParams = req.body;
            if (bodyParams.firstName) {
                profile.firstName = bodyParams.firstName;
            }
            if (bodyParams.lastName) {
                profile.lastName = bodyParams.lastName;
            }
            if (bodyParams.city) {
                profile.city = bodyParams.city;
            }
            if (bodyParams.state) {
                profile.state = bodyParams.state;
            }
            if (bodyParams.country) {
                profile.country = bodyParams.country;
            }
            if (bodyParams.address) {
                profile.address = bodyParams.address;
            }
            if (bodyParams.aboutMe) {
                profile.aboutMe = bodyParams.aboutMe;
            }
            profile.save(function (err) {
                if (!err) {
                    apiHandler.setSuccessResponse(profile, res);
                }
            });
        }
    }));
};

exports.uploadCropped = function (req, res) {
    var img = req.body.img;
    var fileType = ((img).split(";")[0]).split("/")[1];
    var base64 = ((img).split("base64,")[1]);
    var data = {"base64": base64, "fileType": fileType};
    users.uploadCropped(data, req.user._id, apiHandler.handler.check(res, 'PROFILE_UPLOAD_FAILED', function (upload) {
        apiHandler.setSuccessResponse(upload, res);
    }));
};

exports.countries = function (req, res) {
    var countries = countryHelper.countryArray;
    apiHandler.setSuccessResponse(countries, res);
};

exports.getAdminUsers = function (req, res) {
    users.getAdminUsers(req.user, req.body, apiHandler.handler.check(res, 'NO_USERS', function (user) {
        for (var i = 0; i < user.length; i++) {
            var isAdmin = user[i].role.indexOf('admin') >= 0;
            user[i].isAdmin = isAdmin;
        }
        users.getUserCount(req.user, req.body, function (err, ucount) {
            if (!err) {
                var data = {
                    userList: user,
                    userCount: ucount.length
                };
                apiHandler.setSuccessResponse(data, res);

            }
        });
    }));
};

exports.updateStatus = function (req, res) {
    users.updateStatus(req.body, apiHandler.handler.check(res, 'NO_USERS', function (users) {
        apiHandler.setSuccessResponse(users, res);
        if (req.body.state) {
            mailer.sendUpdateStatusMail(users)
                .then(function (success) {
                })
                .catch(function (err) {
                    apiHandler.setErrorResponse('ERROR_WHILE_MAIL_SENDING', res);
                });
        }
    }));
};

exports.addUser = function (req, res) {
    var bodyParams = req.body,
        name = bodyParams.name,
        email = bodyParams.email,
        password = bodyParams.password,
        passwordConfirm = bodyParams.passwordConfirm,
        emailRegex = new RegExp(stringConstant.VALID_EMAIL_REGEX),
        firstName = '', lastName = '', fullName = '', newUser, confirmationToken, confirmationUrl;
    if (!name || !email || !password) {
        apiHandler.setErrorResponse('REQUIRED_FIELDS_MISSING', res);
    } else if (!emailRegex.test(email)) {
        apiHandler.setErrorResponse('INVALID_EMAIL_ADDRESS', res);
    } else if (password && password !== passwordConfirm) {
        apiHandler.setErrorResponse('CONFIRM_PASSWORD_NOT_SAME', res);
    } else {
        fullName = name.split(' ');
        if (fullName.length > 1) {
            lastName = fullName[fullName.length - 1];
            for (var i = 0; i < fullName.length - 1; i++) {
                firstName = firstName + ' ' + fullName[i];
            }
        } else {
            firstName = fullName[0];
            lastName = '';
        }
        bodyParams.firstName = firstName;
        bodyParams.lastName = lastName;
        bodyParams.version = req.body.versioning;

        versionModel.updateVersionCount(bodyParams.version, bodyParams.gender, '', '');

        bodyParams.role = [];
        if (req.body.isAdmin) {
            bodyParams.role.push('user');
            bodyParams.role.push('admin');
        } else {
            bodyParams.role.push('user');
        }

        newUser = new users(bodyParams);
        users.createUser(newUser, function (err, user) {
            if (err) {
                if (err.code === 11000) {
                    apiHandler.setErrorResponse('EMAIL_ALREADY_EXIST', res);
                } else {
                    apiHandler.setErrorResponse('UNKNOWN_ERROR', res);
                }
            } else {
                confirmationToken = jWT.getConfirmationToken(newUser);
                users.updateConfirmationToken(confirmationToken, apiHandler.handler.check(res, 'UNKNOWN_ERROR', function (userDetails) {
                    confirmationUrl = '/v1/users/confirm?token=' + confirmationToken;
                    mailer.sendConfirmationMail(firstName, email, confirmationUrl)
                        .then(function (success) {
                            var token = jWT.getLoginToken(user);
                            var newToken = new authToken({
                                user: user,
                                token: token
                            });
                            authToken.createToken(newToken, function (err, authUser) {
                                if (err) {
                                    req.user = null;
                                    apiHandler.setErrorResponse('LOGIN_FAILED', res);
                                } else {
                                    var data = {
                                        token: token,
                                        user: user
                                    };
                                    apiHandler.setSuccessResponse(data, res);

                                }
                            });
                        })
                        .catch(function (err) {
                            user.remove();
                            apiHandler.setErrorResponse('ERROR_IN_USER_ADDITION', res);
                        });
                }));
            }
        });
    }
};

exports.updateUserInfo = function (req, res) {
    var usersData = req.body;
    users.getUserById(usersData._id, apiHandler.handler.check(res, 'NO_USERS', function (user) {
        var firstName, lastName, name, fullName;
        name = usersData.name;
        fullName = name.split(' ');
        if (fullName.length > 1) {
            lastName = fullName[fullName.length - 1];
            for (var i = 0; i < fullName.length - 1; i++) {
                firstName = fullName[i];
            }
        } else {
            firstName = fullName[0];
            lastName = '';
        }
        usersData.firstName = firstName;
        usersData.lastName = lastName;

        if (usersData) {
            user.address = usersData.address;
            user.city = usersData.city;
            user.state = usersData.state;
            user.country = usersData.country;
            user.aboutMe = usersData.aboutMe;
        }
        if (usersData.firstName) {
            user.firstName = usersData.firstName;
        }
        if (usersData.lastName) {
            user.lastName = usersData.lastName;
        }
        if (usersData.versioning && usersData.versioning != user.version) {
            versionModel.updateVersionCount(usersData.versioning, usersData.gender, user.version, user.gender);
            user.version = usersData.versioning;
        }
        if (usersData.gender && usersData.gender != user.gender) {
            user.gender = usersData.gender;
        }
        if (usersData.isAdmin == true) {
            user.role = ['user', 'admin'];
        }
        if (usersData.isAdmin == false) {
            user.role = ['user'];
        }
        if (usersData.isSuperAdmin == true) {
            user.role.push('superadmin');
        }
        if (usersData.isActive) {
            user.isActive = usersData.isActive;
        }
        user.save();
        apiHandler.setSuccessResponse(user, res);
    }));
};

exports.getRecentUsers = function (req, res) {
    users.getRecentUsers(req.body, apiHandler.handler.check(res, 'NO_USERS', function (users) {
        apiHandler.setSuccessResponse(users, res);
    }));
};

exports.editRole = function (req, res) {
    var params = req.body;
    users.editRole(params.id, params.role, apiHandler.handler.check(res, 'NO_USERS', function (users) {
        apiHandler.setSuccessResponse(users, res);
    }));
};

exports.saveIdea = function (req, res) {
    users.saveIdea(req.user._id, req.body.idea, apiHandler.handler.check(res, 'NO_USERS', function (users) {
        apiHandler.setSuccessResponse(users, res);
    }));
};

exports.getSavedIdea = function (req, res) {
    users.getSavedIdea(req.user._id, apiHandler.handler.check(res, 'NO_USERS', function (users) {
        apiHandler.setSuccessResponse(users, res);
    }));
};